package com.gdust.gkyx.acl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gdust.gkyx.acl.mapper.RoleMapper;
import com.gdust.gkyx.acl.service.AdminRoleService;
import com.gdust.gkyx.acl.service.RoleService;
import com.gdust.gkyx.model.acl.AdminRole;
import com.gdust.gkyx.model.acl.Role;
import com.gdust.gkyx.vo.acl.RoleQueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * ClassName: RoleServiceImpl
 * Package: com.gdust.gkyx.acl.service.impl
 * Description:角色服务实现类，负责角色相关的业务逻辑处理。
 *
 * @Author syun
 * @Create 2025/1/21 15:25
 * @Version 1.0
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    /**
     * //注入用户角色关系表的service
     */
    @Autowired
    private AdminRoleService adminRoleService;


    /**
     * //1 角色列表（条件分页查询）
     * @param pageParam 分页对象
     * @param roleQueryVo 查询条件：包含角色名称
     * @return
     */
    //1 角色列表（条件分页查询）
    @Override
    public IPage<Role> selectRolePage(Page<Role> pageParam,
                                      RoleQueryVo roleQueryVo) {
        //获取条件值:角色名称
        String roleName = roleQueryVo.getRoleName();

        //创建mp条件对象
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();

        //判断条件值是否为空，不为空则封装查询条件
        // 类似于SQL写法：rolename like ?
        if(!StringUtils.isEmpty(roleName)) {
            //根据角色名称进行模糊查询
            wrapper.like(Role::getRoleName,roleName);
        }

        //调用方法实现条件分页查询
        //注：ServiceImpl(IService 实现类)已集成baseMapper，
        // 由于 ServiceImpl<RoleMapper, Role> 已经指定了 RoleMapper 作为类型参数，因此 baseMapper 实际上是 RoleMapper 的实例，可以直接用来执行分页查询操作。
        IPage<Role> rolePage = baseMapper.selectPage(pageParam, wrapper);

        //返回分页对象
        return rolePage;
    }

    /**
     * 获取所有角色，和根据用户id查询用户分配角色列表
     * @param adminId 会员id
     * @return
     */
    @Transactional
    @Override
    public Map<String, Object> getRoleByAdminId(Long adminId) {
        //1 查询所有角色,null为没有条件查询全部。
        // 由于 ServiceImpl<RoleMapper, Role> 已经指定了 RoleMapper 作为类型参数，因此 baseMapper 实际上是 RoleMapper 的实例，可以直接用来执行查询操作。
        List<Role> allRolesList = baseMapper.selectList(null);

        //2 根据用户id查询用户分配角色列表
        //2.1 根据用户id查询 用户角色关系表 admin_role 查询用户分配角色id列表
        // List<AdminRole>
        LambdaQueryWrapper<AdminRole> wrapper = new LambdaQueryWrapper<>();
        //设置查询条件，根据用户id adminId
        wrapper.eq(AdminRole::getAdminId,adminId);
        //根据条件用户id，查询用户分配角色列表
        List<AdminRole> adminRoleList = adminRoleService.list(wrapper);

        //2.2 通过第一步返回集合，获取所有角色id的列表List<AdminRole> -- List<Long>
        // 从 adminRoleList 中提取所有的 roleId 并将其转换为一个 List<Long>
        List<Long> roleIdsList =
                adminRoleList.stream()// 将 adminRoleList 转换为一个 Stream 流以便进行操作
                        .map(item -> item.getRoleId())// 使用 map 方法从每个元素中提取 roleId 属性
                        .collect(Collectors.toList());// 将提取的 roleId 收集到一个 List 中

        //2.3 创建新的list集合，用于存储用户配置角色
        List<Role> assignRoleList = new ArrayList<>();

        //2.4 遍历所有角色列表 allRolesList，得到每个角色
        //判断所有角色里面是否包含已经分配角色id，封装到2.3里面新的list集合
        for (Role role:allRolesList) {
            //判断
            if(roleIdsList.contains(role.getId())) {
                assignRoleList.add(role);
            }
        }

        //封装到map，返回
        Map<String, Object> result = new HashMap<>();
        //所有角色列表
        result.put("allRolesList",allRolesList);
        //用户分配角色列表
        result.put("assignRoles",assignRoleList);
        return result;
    }

    /**
     * //为用户进行分配
     *
     * 思路：全量更新。在更新时，先清除旧的所有数据，再插入新的完整数据。
     *
     * @param adminId 会员id
     * @param roleIds 角色id
     */
    @Transactional
    @Override
    public void saveAdminRole(Long adminId, Long[] roleIds) {
        //1 删除用户已经分配过的角色数据
        //根据用户id删除admin_role表里面对应数据
        LambdaQueryWrapper<AdminRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdminRole::getAdminId,adminId);
        adminRoleService.remove(wrapper);

        //2 重新分配
        //adminId:1   roleId: 2 3
        //遍历多个角色id，得到每个角色id，拿着每个角色id + 用户id添加用户角色关系表
//        for (Long roleId:roleIds) {
//            AdminRole adminRole = new AdminRole();
//            adminRole.setAdminId(adminId);
//            adminRole.setRoleId(roleId);
//            adminRoleService.save(adminRole);
//        }
        //改进：遍历多次仅保存一次到数据库
        List<AdminRole> list = new ArrayList<>();
        for (Long roleId: roleIds) {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(adminId);
            adminRole.setRoleId(roleId);
            //放到list集合
            list.add(adminRole);
        }
        //调用方法添加
        adminRoleService.saveBatch(list);
    }


}
